/* 
Copyright (c) 2004,2005, 2006, 2007, 2008 University of Illinois 

All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:

1. Redistributions of source code must retain the above copyright
   notice, this list of conditions and the following disclaimer.

2. Redistributions in binary form must reproduce the above copyright
   notice, this list of conditions and the following disclaimer in the
   documentation and/or other materials provided with the distribution.

3. The name of the author may not be used to endorse or promote products
   derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
AccessibilityExtension.ns(function() { with (AccessibilityExtension.LIB) {

	/** @class Encapsulates details for features of the toggling variety.
	 * FIXME: This should descend from a parent "Feature" class.
	 * @constructor
	 * @param name String - Name used to reference this this feature
	 * @param prefStr String - Preferences name/id where the state of this feature would be stored
	 * @param bcastID String - The broadcaster ID that mostly controls the checked state of a menu item
	 * @param callback String - Function that implements this feature.
	 * @param prefDriven String - Whether state is stored in the about:config preferences?
	 * @param initialState Initial state
	 * @returns None
	 */
	AccessibilityExtension.LIB.accessextToggleFeature = function (name,prefStr,bcastID,callback,prefDriven,initialState) {
			this.name = name;
			this.prefStr = prefStr;
			this.bcastID = bcastID;
			this.callback = callback;
			this.type = 'toggle';
			this.prefDriven = prefDriven;
			this.initialState = initialState;
		},
		
		/** @class Encapsulates the various names and associated functionality of a feature, provides access methods.
		 * @constructor
		 */
		AccessibilityExtension.LIB.accessextFeatures = function () {
			this.addToggleFeature('textequivall-hide','textequivall.hide','accessext-bcast-textequivall-hide',accessext_handle_textequivall_hide,false,false);
			this.addToggleFeature('objects-hide','objects.hide','accessext-bcast-objects-hide',accessext_handle_objects_hide,false,false);
			this.addToggleFeature('images-hide','images.hide','accessext-bcast-images-hide',accessext_handle_images_hide,false,false);
			this.addToggleFeature('images-replaceWithAlt','images.replaceWithAlt','accessext-bcast-images-replaceWithAlt',accessext_handle_images_replaceWithAlt,false,false);
			this.addToggleFeature('images-hide-backgrounds','images.disable.backgrounds','accessext-bcast-images-hide-backgrounds',accessext_handle_images_disable_backgrounds,false,false);
			this.addToggleFeature('css-tables-enabled','styles.css.tables.enabled','accessext-bcast-css-tables-enabled',accessext_handle_styles_tables_enabled,true,false);
			this.addToggleFeature('disable-accesskeys','accesskeys.disable','accessext-bcast-accesskeys-disable',accessext_handle_options_accesskeys_disable,false,false);
			this.addToggleFeature('author-css-enabled','styles.author.css.enabled','accessext-bcast-author-css-enabled',accessext_handle_styles_css_enabled,true,false);
			this.addToggleFeature('css-tags-enabled','styles.css.tags.enabled','accessext-bcast-css-tags-enabled',accessext_handle_styles_css_tags_enabled,true,false);
			this.addToggleFeature('expand-abbr','styles.expandAbbr','accessext-bcast-expandAbbr',accessext_handle_expandAbbr,false,false);
			this.addToggleFeature('userstyle-enable','styles.userStylesheet.enable','accessext-bcast-styles-userStylesheet-enable',accessext_handle_styles_userStylesheet_enable,false,false);
			this.addToggleFeature('events-disable-mouse','events.disable.mouse','accessext-bcast-events-disable-mouse',AccessibilityExtension.LIB.accessext_handle_events_toggle_mouse,false,false);
			this.addToggleFeature('events-disable-window','events.disable.window','accessext-bcast-events-disable-window',AccessibilityExtension.LIB.accessext_handle_events_toggle_window,false,false);
			this.addToggleFeature('events-disable-forms','events.disable.forms','accessext-bcast-events-disable-forms',AccessibilityExtension.LIB.accessext_handle_events_toggle_forms,false,false);
			this.addToggleFeature('styles-highcontrast','styles.highcontrast','accessext-bcast-styles-highcontrast',AccessibilityExtension.LIB.accessext_handle_highcontrast,false,false);
			this.addToggleFeature('styles-highcontrast2','styles.highcontrast2','accessext-bcast-styles-highcontrast2',AccessibilityExtension.LIB.accessext_handle_highcontrast2,false,false);	
			this.addToggleFeature('showDataTableTitles','styles.showDataTableTitles','accessext-bcast-showDataTableTitles',AccessibilityExtension.LIB.accessext_handle_showDataTableTitles,false,false);
			
			this.addToggleFeature('accessext-keyboardEnhancements','keyboardnav.enabled','accessext-bcast-keyboardnav-enabled',AccessibilityExtension.LIB.accessext_handle_keyboardNavEnabled,true,false);
		
			this.addToggleFeature('disable-meta-refresh','disableMetaRefresh','accessext-bcast-events-disable-meta',AccessibilityExtension.LIB.accessext_handle_disableMetaRefresh,false,false);
			this.addToggleFeature('disable-scripting','disableScripting','accessext-bcast-events-disable-scripting',AccessibilityExtension.LIB.accessext_handle_disableJavascript,false,false);	
			
			this.addToggleFeature('standards-useDom','standards.useDom','accessext-bcast-standards-useDom',AccessibilityExtension.LIB.accessext_handle_standards_useDom,true,false);
			this.addToggleFeature('standards-newWindow','standards.newWindow','accessext-bcast-standards-newWindow',AccessibilityExtension.LIB.accessext_handle_standards_newWindow,true,false);
		//TODO: This never worked	this.addToggleFeature('accessext-showTOCMenu','options.showTOCMenu','accessext-bcast-keyboardnav-enabled',accessext_handle_keyboardNavEnabled,true);
		};
		
		AccessibilityExtension.LIB.accessextToggleFeature.prototype = {
			/** Feature name */
			name : false,
			/** Name/Id in preferences */
			prefStr : false,
			/** Id of broadcaster that tends to maintains menu checked state and may encapsulate the state of a feature when not using global preferences? */
			bcastID : false,
			/** Function implementing the feature.  For a toggle feature, this must have a method signature of the form foo(checkedStatusBoolean, domDocumentNodesToAffectArray). */
			callback : null,
			/** Whether the state of this feature may be stored in the Mozilla preferences */
			prefDriven : false,
			/** Initial boolean state of the feature */
			initialState : false,
		
			/** Sets the status of this feature.  
			 * Status is recorded to the preferences if the global preference mode is active and this feature is prefDriven.
			 * The broadcaster is updated to reflect the new status.
			 * @param status Boolean - New state of feature
			 * @returns None
			 */
			updateToggle : function(status) {
				var bc = document.getElementById(this.bcastID);
				
				if (this.prefDriven || accessext_getActivePreferenceMode() == 'global') {
		//			accessext_consoleDump('Pref driven status for ' + this.name + ' set to ' + (status ? "true" : "false") + "(pref string is " + this.prefStr + ")");
					var pref = getAccessextPrefService();
					pref.setBoolPref(this.prefStr,status);
				} else {
		//			accessext_consoleDump('DOC driven status for ' + this.name + ' set to ' + (status ? "true" : "false"));
				}
				if (bc) {
					bc.setAttribute("checked",(status ? "true" : "false"));
				} else {
					accessext_consoleDump("Broadcaster element not found: " + this.bcastID);
				}
			},
			
			/** Get state of this feature.
			 * FIXME: Horrible interface, especially the returns and error checking.
			 * Gets the state of the feature from the preferences or broadcaster depending on the preference mode and the prefDriven of this feature.
			 * FIXME: This is very unreliable in the case of the broadcaster and should be rewritten.
			 * @returns Boolean state of the feature.  Defaults to false or null if feature is not stored in the right place.
			 */
			getToggleStatus : function() {
				if (this.prefDriven || accessext_getActivePreferenceMode() == 'global') {
					var pref = getAccessextPrefService();
					if (pref.prefHasUserValue(this.prefStr)) {
		//				accessext_consoleDump('Checking toggle status for ' + this.prefStr + " : " + (pref.getBoolPref(this.prefStr) ? "true" : "false"));
						return pref.getBoolPref(this.prefStr);
					} else {
						accessext_consoleDump('Value for user pref not found ' + this.prefStr);
					}
					
					return false;
				}
				var bc = document.getElementById(this.bcastID);
				if (bc) {
					return bc.getAttribute("checked") == 'true';
				} else {
					accessext_consoleDump("Broadcaster element not found: " + this.bcastID);
					return null;
				}
			}
		};	
	AccessibilityExtension.LIB.accessextFeatures.prototype = {
			/**
			 * Array of feature objects
			 * @private
			 */
			features : Array(),
			/*addRadioFeature : function(name,prefStr,broadcasters,callback,prefDriven) {
				//Not implemented yet
			},*/
			/**
			 * Adds a toggle feature
			 * @param name String - Name used to reference this this feature
			 * @param prefStr String - Preferences name/id where the state of this feature would be stored
			 * @param bcastID String - The broadcaster ID that mostly controls the checked state of a menu item
			 * @param callback String - Function that implements this feature
			 * @param prefDriven String - Whether state is stored in the about:config preferences?
			 * @param initialState Initial state
			 * @returns None
			 */
			addToggleFeature : function(name,prefStr,bcastID,callback,prefDriven,initialState) {
				this.features[name] = new accessextToggleFeature(name,prefStr,bcastID,callback,prefDriven,initialState);
			},
			/** Sets the state of a toggle feature
			 * @param checked Boolean - State of the feature
			 * @returns None
			 */
			setToggleStatus : function(name,checked) {
				if (this.features[name]) {
					this.features[name].updateToggle(checked);
				}
			},
			/** Existance of given feature
			 * @param name String - Name of the preference
			 * @returns True if the feature exists, else False
			 * @type Boolean
			 */
			featureAvailable : function(name) {
				return (this.features && this.features[name]);
			},
			/** Gets a feature's value
			 * @param name String - Name of the preference
			 * @returns The value of the preference; possibly any datatype
			 */
			getFeature : function(name) {
				return (this.features[name] ? this.features[name] : null);
			},
			/** Gets a list of all recognized feature names.
			 * @returns An array of all feature names (Strings).
			 * @type Array of String
			 */
			getListOfFeatures : function() {
				var f = new Array();
				for (var a in this.features) {
					f[f.length] = a;
				}
				return f;
			}
		};
}});	